package net.qiqb.module;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import net.qiqb.module.spring.SpringModuleContext;
import org.springframework.beans.factory.BeanFactory;

import java.lang.reflect.Constructor;

public class ModuleServiceConfig<T> {

    private final ModuleContext moduleContext;

    private String localImplClassName;
    /**
     * 实际的实现
     */
    private T target;
    /**
     * 接口类名
     */
    private final String interfaceClassName;

    private final Class<T> interfaceClass;


    private boolean init = false;

    public ModuleServiceConfig(ModuleContext moduleContext, String interfaceClassName) {
        this.moduleContext = moduleContext;
        this.interfaceClassName = interfaceClassName;
        this.interfaceClass = ClassUtil.loadClass(interfaceClassName);
    }


    public void setLocalImplClass(String localImplClass) {
        this.localImplClassName = localImplClass;
    }

    public Object getTarget() {
        if (!init) {
            init();
        }
        return target;
    }


    public synchronized void init() {
        init = true;
        if (target == null) {
            if (localImplClassName == null) {
                // 直接获取引用对象
                for (ModuleServiceDispatcher serviceDispatcher : this.moduleContext.getServiceDispatchers()) {
                    T candidateTarget = serviceDispatcher.refer(interfaceClass);
                    if (candidateTarget != null) {
                        this.target = candidateTarget;
                        break;
                    }
                }

            } else {
                // 自己创建
                final T newTarget = createTarget();
                if (newTarget != null) {
                    this.target = newTarget;
                    // 暴露出去
                    for (ModuleServiceDispatcher serviceDispatcher : this.moduleContext.getServiceDispatchers()) {
                        serviceDispatcher.dispatch(interfaceClass, target);
                    }
                }
            }
        }
    }

    private T createTarget() {
        if (localImplClassName != null) {
            final Class<Object> localImplClass = ClassUtil.loadClass(localImplClassName);
            final Constructor<Object>[] constructors = ReflectUtil.getConstructors(localImplClass);
            if (constructors.length != 1) {
                throw new IllegalStateException(localImplClass.getName() + " module service 只能有一个构造器");
            }
            // 获取构造器参数
            Constructor<?> constructor = constructors[0];
            Object[] parameterValues = new Object[constructor.getParameterCount()];

            int i = 0;
            for (Class<?> parameterType : constructor.getParameterTypes()) {
                if (moduleContext instanceof SpringModuleContext springModuleContext) {
                    //
                    final BeanFactory beanFactory = springModuleContext.getBeanFactory();
                    parameterValues[i] = beanFactory.getBean(parameterType);
                    i++;
                }
            }
            try {
                return (T) constructors[0].newInstance(parameterValues);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

}
